package com.information.service.impl;

import com.information.entity.User;
import com.information.repository.UserRepository;
import com.information.service.OperationLogService;
import com.information.service.RedisService;
import com.information.service.UserEventProducer;
import com.information.service.UserService;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;
    private final OperationLogService operationLogService;
    private final RedisService redisService;

    @Autowired
    private UserEventProducer userEventProducer;

    @Autowired
    public UserServiceImpl(UserRepository userRepository, OperationLogService operationLogService, RedisService redisService) {
        this.userRepository = userRepository;
        this.operationLogService = operationLogService;
        this.redisService = redisService;
    }

    @Override
    @Transactional(readOnly = true)
    public List<User> findAllUsers() {
        // 先从缓存获取
        List<User> cachedUsers = redisService.getCachedAllUsers();
        if (cachedUsers != null) {
            return cachedUsers;
        }

        // 缓存未命中，从数据库查询未删除的用户
        List<User> users = userRepository.findAllActiveUsers();

        // 缓存查询结果
        redisService.cacheAllUsers(users);

        return users;
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<User> findUserById(Long id) {
        // 先从缓存获取
        User cachedUser = redisService.getCachedUser(id);
        if (cachedUser != null && !cachedUser.getIsDelete()) {
            return Optional.of(cachedUser);
        }

        // 缓存未命中，从数据库查询
        Optional<User> userOpt = userRepository.findByIdAndNotDeleted(id);

        // 缓存查询结果
        userOpt.ifPresent(user -> {
            redisService.cacheUser(user);
            redisService.cacheUserByUsername(user);
        });

        return userOpt;
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<User> findUserByUsername(String username) {
        // 先从缓存获取
        User cachedUser = redisService.getCachedUserByUsername(username);
        if (cachedUser != null && !cachedUser.getIsDelete()) {
            return Optional.of(cachedUser);
        }

        // 缓存未命中，从数据库查询
        Optional<User> userOpt = userRepository.findByUsernameAndNotDeleted(username);

        // 缓存查询结果
        userOpt.ifPresent(user -> {
            redisService.cacheUser(user);
            redisService.cacheUserByUsername(user);
        });

        return userOpt;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public User saveUser(User user, String operatedBy) {
        // 设置默认值
        if (user.getRole() == null) {
            user.setRole(User.UserRole.USER);
        }
        if (user.getIsDelete() == null) {
            user.setIsDelete(false);
        }
        if (user.getStatus() == null) {
            user.setStatus(User.UserStatus.ACTIVE);
        }

        // 确保创建和更新时间已设置
        if (user.getCreatedAt() == null) {
            user.setCreatedAt(LocalDateTime.now());
        }
        if (user.getUpdatedAt() == null) {
            user.setUpdatedAt(LocalDateTime.now());
        }

        // 保存用户
        User savedUser = userRepository.save(user);

        // 缓存新用户并清除用户列表缓存
        redisService.cacheUser(savedUser);
        redisService.cacheUserByUsername(savedUser);
        redisService.evictAllUsers();

        // 发送用户事件到消息队列（异步记录日志）
        try {
            userEventProducer.sendUserEvent("CREATE", savedUser, operatedBy);
        } catch (Exception e) {
            System.err.println("发送用户创建事件失败: " + e.getMessage());
        }

        return savedUser;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public User updateUser(Long id, User userDetails, String operatedBy) {
        User existingUser = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户ID未找到: " + id));

        String oldUsername = existingUser.getUsername();

        // 获取操作者信息进行权限检查
        User operator = userRepository.findByUsernameAndNotDeleted(operatedBy)
                .orElseThrow(() -> new RuntimeException("操作者未找到: " + operatedBy));

        // 权限检查：只有超级管理员可以操作超级管理员，且不能操作自己
        if (existingUser.getRole() == User.UserRole.SUPER_ADMIN) {
            if (operator.getRole() != User.UserRole.SUPER_ADMIN) {
                throw new RuntimeException("权限不足：只有超级管理员可以操作超级管理员账户");
            }
            if (operator.getId().equals(existingUser.getId())) {
                throw new RuntimeException("不能编辑自己的信息");
            }
        }

        // 更新用户信息
        if (userDetails.getUsername() != null) {
            existingUser.setUsername(userDetails.getUsername());
        }
        if (userDetails.getPassword() != null) {
            existingUser.setPassword(userDetails.getPassword());
        }
        if (userDetails.getName() != null) {
            existingUser.setName(userDetails.getName());
        }
        if (userDetails.getEmail() != null) {
            existingUser.setEmail(userDetails.getEmail());
        }
        if (userDetails.getPhone() != null) {
            existingUser.setPhone(userDetails.getPhone());
        }
        if (userDetails.getAge() != null) {
            existingUser.setAge(userDetails.getAge());
        }
        if (userDetails.getGender() != null) {
            existingUser.setGender(userDetails.getGender());
        }
        if (userDetails.getAddress() != null) {
            existingUser.setAddress(userDetails.getAddress());
        }
        if (userDetails.getRole() != null) {
            existingUser.setRole(userDetails.getRole());
        }
        if (userDetails.getStatus() != null) {
            existingUser.setStatus(userDetails.getStatus());
        }

        existingUser.setUpdatedAt(LocalDateTime.now());

        User updatedUser = userRepository.save(existingUser);

        // 更新缓存
        redisService.cacheUser(updatedUser);
        redisService.cacheUserByUsername(updatedUser);

        // 如果用户名发生变化，清除旧用户名的缓存
        if (!oldUsername.equals(updatedUser.getUsername())) {
            redisService.evictUserByUsername(oldUsername);
        }

        // 清除用户列表缓存
        redisService.evictAllUsers();

        // 发送用户事件到消息队列（异步记录日志）
        try {
            userEventProducer.sendUserEvent("UPDATE", updatedUser, operatedBy);
        } catch (Exception e) {
            System.err.println("发送用户更新事件失败: " + e.getMessage());
        }

        return updatedUser;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void deleteUser(Long id, String operatedBy) {
        User user = userRepository.findByIdAndNotDeleted(id)
                .orElseThrow(() -> new RuntimeException("用户ID未找到: " + id));

        // 获取操作者信息进行权限检查
        User operator = userRepository.findByUsernameAndNotDeleted(operatedBy)
                .orElseThrow(() -> new RuntimeException("操作者未找到: " + operatedBy));

        // 权限检查：只有超级管理员可以操作超级管理员，且不能操作自己
        if (user.getRole() == User.UserRole.SUPER_ADMIN) {
            if (operator.getRole() != User.UserRole.SUPER_ADMIN) {
                throw new RuntimeException("权限不足：只有超级管理员可以操作超级管理员账户");
            }
            if (operator.getId().equals(user.getId())) {
                throw new RuntimeException("不能删除自己");
            }
        }

        // 保存用户名用于后续缓存清除
        String username = user.getUsername();

        try {
            operationLogService.logOperation("DELETE", user, operatedBy);
        } catch (Exception e) {
            System.err.println("删除用户前记录日志失败: " + e.getMessage());
            e.printStackTrace();
        }

        // 软删除：设置is_delete为true
        user.setIsDelete(true);
        user.setUpdatedAt(LocalDateTime.now());
        userRepository.save(user);

        // 强制刷新事务，确保数据库更新完成
        userRepository.flush();

        // 发送用户事件到消息队列（异步记录日志）
        try {
            userEventProducer.sendUserEvent("DELETE", user, operatedBy);
        } catch (Exception e) {
            System.err.println("发送用户删除事件失败: " + e.getMessage());
        }

        // 立即清除相关缓存
        redisService.evictUser(id);
        redisService.evictUserByUsername(username);
        redisService.evictAllUsers();

    }

    @Override
    @Transactional(readOnly = true)
    public boolean existsByUsername(String username) {
        return userRepository.existsByUsernameAndNotDeleted(username);
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<User> login(String username, String password) {
        return userRepository.findByUsernameAndPasswordAndNotDeleted(username, password);
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public User updateUserStatus(Long id, String status, String operatedBy) {
        User user = userRepository.findByIdAndNotDeleted(id)
                .orElseThrow(() -> new RuntimeException("用户ID未找到: " + id));

        // 获取操作者信息
        User operator = userRepository.findByUsernameAndNotDeleted(operatedBy)
                .orElseThrow(() -> new RuntimeException("操作者未找到: " + operatedBy));

        // 权限检查：只有超级管理员可以操作超级管理员，且不能操作自己
        if (user.getRole() == User.UserRole.SUPER_ADMIN) {
            if (operator.getRole() != User.UserRole.SUPER_ADMIN) {
                throw new RuntimeException("权限不足：只有超级管理员可以操作超级管理员账户");
            }
            if (operator.getId().equals(user.getId())) {
                throw new RuntimeException("不能修改自己的状态");
            }
        }


        // 更新状态
        User.UserStatus newStatus;
        try {
            newStatus = User.UserStatus.valueOf(status);
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("无效的状态值: " + status);
        }

        user.setStatus(newStatus);
        user.setUpdatedAt(LocalDateTime.now());
        User updatedUser = userRepository.save(user);

        // 更新缓存
        redisService.cacheUser(updatedUser);
        redisService.cacheUserByUsername(updatedUser);
        redisService.evictAllUsers();

        // 发送用户事件到消息队列（异步记录日志）
        try {
            userEventProducer.sendUserEvent("STATUS_UPDATE", updatedUser, operatedBy);
        } catch (Exception e) {
            System.err.println("发送用户状态更新事件失败: " + e.getMessage());
        }

        return updatedUser;
    }

    @Override
    public boolean canOperateOnUser(Long operatorId, String operatorRole, Long targetUserId) {
        if (operatorId.equals(targetUserId)) {
            return false; // 不能操作自己
        }

        // 获取目标用户信息
        Optional<User> targetUserOpt = userRepository.findByIdAndNotDeleted(targetUserId);
        if (!targetUserOpt.isPresent()) {
            return false;
        }

        User targetUser = targetUserOpt.get();
        User.UserRole operatorRoleEnum = User.UserRole.valueOf(operatorRole);

        // 如果目标用户是超级管理员，只有超级管理员可以操作
        if (targetUser.getRole() == User.UserRole.SUPER_ADMIN) {
            return operatorRoleEnum == User.UserRole.SUPER_ADMIN;
        }

        // 其他情况：管理员和超级管理员都可以操作普通用户和管理员
        return operatorRoleEnum == User.UserRole.SUPER_ADMIN || operatorRoleEnum == User.UserRole.ADMIN;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public Map<String, Integer> importUsersFromExcel(MultipartFile file, String operatedBy) throws Exception {
        Map<String, Integer> result = new HashMap<>();
        int successCount = 0;
        int failCount = 0;
        List<String> errorMessages = new ArrayList<>();

        try (InputStream inputStream = file.getInputStream()) {
            // 根据文件类型创建工作簿
            Workbook workbook;
            String fileName = file.getOriginalFilename();
            if (fileName != null && fileName.endsWith(".xlsx")) {
                workbook = new XSSFWorkbook(inputStream);
            } else if (fileName != null && fileName.endsWith(".xls")) {
                workbook = new HSSFWorkbook(inputStream);
            } else {
                throw new RuntimeException("不支持的文件格式，请上传.xlsx或.xls文件");
            }

            Sheet sheet = workbook.getSheetAt(0);

            // 验证表头
            Row headerRow = sheet.getRow(0);
            if (headerRow == null) {
                throw new RuntimeException("Excel文件格式错误：缺少表头");
            }

            // 验证必要的列是否存在
            String[] expectedHeaders = {"用户名", "密码", "姓名", "邮箱", "电话", "年龄", "性别", "地址", "角色"};
            if (headerRow.getLastCellNum() < expectedHeaders.length) {
                throw new RuntimeException("Excel文件格式错误：列数不足");
            }

            // 从第2行开始处理数据（跳过表头和示例行）
            for (int rowIndex = 2; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
                Row row = sheet.getRow(rowIndex);
                if (row == null || isEmptyRow(row)) {
                    continue; // 跳过空行
                }

                try {
                    User user = parseUserFromRow(row, rowIndex);
                    if (user != null) {
                        // 检查用户名是否已存在
                        if (userRepository.existsByUsernameAndNotDeleted(user.getUsername())) {
                            failCount++;
                            errorMessages.add("第" + (rowIndex + 1) + "行：用户名'" + user.getUsername() + "'已存在");
                            continue;
                        }

                        // 保存用户
                        User savedUser = saveUser(user, operatedBy);
                        if (savedUser != null) {
                            successCount++;
                        } else {
                            failCount++;
                            errorMessages.add("第" + (rowIndex + 1) + "行：保存用户失败");
                        }
                    }
                } catch (Exception e) {
                    failCount++;
                    errorMessages.add("第" + (rowIndex + 1) + "行：" + e.getMessage());
                    System.err.println("处理第" + (rowIndex + 1) + "行数据失败: " + e.getMessage());
                }
            }

            workbook.close();

            // 打印错误信息（可选）
            if (!errorMessages.isEmpty()) {
                System.err.println("导入过程中的错误信息:");
                errorMessages.forEach(System.err::println);
            }

        } catch (Exception e) {
            System.err.println("Excel文件处理失败: " + e.getMessage());
            throw new RuntimeException("Excel文件处理失败: " + e.getMessage(), e);
        }

        result.put("success", successCount);
        result.put("fail", failCount);

        return result;
    }

    /**
     * 从Excel行解析用户对象
     */
    private User parseUserFromRow(Row row, int rowIndex) throws Exception {
        User user = new User();

        try {
            // 用户名 (必填)
            String username = getCellStringValue(row.getCell(0));
            if (username == null || username.trim().isEmpty()) {
                throw new RuntimeException("用户名不能为空");
            }
            user.setUsername(username.trim());

            // 密码 (必填)
            String password = getCellStringValue(row.getCell(1));
            if (password == null || password.trim().isEmpty()) {
                throw new RuntimeException("密码不能为空");
            }
            user.setPassword(password.trim());

            // 姓名 (可选)
            String name = getCellStringValue(row.getCell(2));
            if (name != null && !name.trim().isEmpty()) {
                user.setName(name.trim());
            }

            // 邮箱 (可选)
            String email = getCellStringValue(row.getCell(3));
            if (email != null && !email.trim().isEmpty()) {
                if (!isValidEmail(email.trim())) {
                    throw new RuntimeException("邮箱格式不正确: " + email);
                }
                user.setEmail(email.trim());
            }

            // 电话 (可选)
            String phone = getCellStringValue(row.getCell(4));
            if (phone != null && !phone.trim().isEmpty()) {
                user.setPhone(phone.trim());
            }

            // 年龄 (可选)
            String ageStr = getCellStringValue(row.getCell(5));
            if (ageStr != null && !ageStr.trim().isEmpty()) {
                try {
                    int age = Integer.parseInt(ageStr.trim());
                    if (age < 0 || age > 150) {
                        throw new RuntimeException("年龄必须在0-150之间");
                    }
                    user.setAge(age);
                } catch (NumberFormatException e) {
                    throw new RuntimeException("年龄格式不正确: " + ageStr);
                }
            }

            // 性别 (可选)
            String gender = getCellStringValue(row.getCell(6));
            if (gender != null && !gender.trim().isEmpty()) {
                gender = gender.trim();
                if (!gender.equals("男") && !gender.equals("女")) {
                    throw new RuntimeException("性别只能是'男'或'女'");
                }
                user.setGender(gender);
            }

            // 地址 (可选)
            String address = getCellStringValue(row.getCell(7));
            if (address != null && !address.trim().isEmpty()) {
                user.setAddress(address.trim());
            }

            // 角色 (必填)
            String roleStr = getCellStringValue(row.getCell(8));
            if (roleStr == null || roleStr.trim().isEmpty()) {
                throw new RuntimeException("角色不能为空");
            }

            try {
                User.UserRole role = User.UserRole.valueOf(roleStr.trim().toUpperCase());
                user.setRole(role);
            } catch (IllegalArgumentException e) {
                throw new RuntimeException("角色值不正确，只能是: USER, ADMIN, SUPER_ADMIN");
            }

            // 设置默认值
            user.setIsDelete(false);
            user.setStatus(User.UserStatus.ACTIVE);
            user.setCreatedAt(LocalDateTime.now());
            user.setUpdatedAt(LocalDateTime.now());

            return user;

        } catch (Exception e) {
            throw new RuntimeException("数据格式错误: " + e.getMessage());
        }
    }

    /**
     * 获取单元格字符串值
     */
    private String getCellStringValue(Cell cell) {
        if (cell == null) {
            return null;
        }

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    // 处理数字，避免科学计数法
                    double numericValue = cell.getNumericCellValue();
                    if (numericValue == Math.floor(numericValue)) {
                        return String.valueOf((long) numericValue);
                    } else {
                        return String.valueOf(numericValue);
                    }
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            case BLANK:
            default:
                return null;
        }
    }

    @Override
    @Transactional(readOnly = true)
    public List<User> findDeletedUsers() {
        return userRepository.findAllDeletedUsers();
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public User restoreUser(Long id, String operatedBy) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户ID未找到: " + id));

        if (!user.getIsDelete()) {
            throw new RuntimeException("用户未被删除，无需恢复");
        }

        // 检查用户名是否已被其他用户使用
        if (userRepository.existsByUsernameAndNotDeleted(user.getUsername())) {
            throw new RuntimeException("用户名已被占用，无法恢复");
        }

        // 恢复用户
        user.setIsDelete(false);
        user.setUpdatedAt(LocalDateTime.now());
        User savedUser = userRepository.save(user);

        // 清除缓存
        redisService.evictUser(id);
        redisService.evictUserByUsername(user.getUsername());
        redisService.evictAllUsers();


        // 发送用户事件到消息队列（异步记录日志）
        try {
            userEventProducer.sendUserEvent("RESTORE", savedUser, operatedBy);
        } catch (Exception e) {
            System.err.println("发送用户恢复事件失败: " + e.getMessage());
        }
        return savedUser;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void permanentDeleteUser(Long id, String operatedBy) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户ID未找到: " + id));

        if (!user.getIsDelete()) {
            throw new RuntimeException("用户未被删除，无法彻底删除");
        }

        String username = user.getUsername();

        // 发送用户事件到消息队列（异步记录日志）
        try {
            userEventProducer.sendUserEvent("PERMANENT_DELETE", user, operatedBy);
        } catch (Exception e) {
            System.err.println("发送用户彻底删除事件失败: " + e.getMessage());
        }

        // 物理删除用户
        userRepository.delete(user);

        // 清除缓存
        redisService.evictUser(id);
        redisService.evictUserByUsername(username);
        redisService.evictAllUsers();

    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int clearRecycleBin(String operatedBy) {
        List<User> deletedUsers = userRepository.findAllDeletedUsers();
        int count = deletedUsers.size();

        // 为每个用户发送彻底删除事件
        for (User user : deletedUsers) {
            try {
                userEventProducer.sendUserEvent("PERMANENT_DELETE", user, operatedBy);
            } catch (Exception e) {
                System.err.println("发送清空回收站事件失败: " + e.getMessage());
            }
        }

        // 批量物理删除
        userRepository.deleteAll(deletedUsers);

        // 清除所有用户缓存
        redisService.evictAllUsers();

        return count;
    }

    /**
     * 检查是否为空行
     */
    private boolean isEmptyRow(Row row) {
        if (row == null) {
            return true;
        }

        for (int i = 0; i < row.getLastCellNum(); i++) {
            Cell cell = row.getCell(i);
            if (cell != null && cell.getCellType() != CellType.BLANK) {
                String value = getCellStringValue(cell);
                if (value != null && !value.trim().isEmpty()) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 简单的邮箱格式验证
     */
    private boolean isValidEmail(String email) {
        return email != null && email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$");
    }
}